
#include "stdafx.h"
#include <GLES2/gl2.h>

GLuint vbo[2];
GLuint prog;
GLuint vao;

EGLDisplay display;
EGLSurface surface;
GLshort indices[3] = { 0,1,2 };
GLfloat vertices[21] = {
		-0.5f,-0.5f,0.0f,   //v0
		1.0f,0.0f,0.0f,1.0f, //c0
		0.0f,.5f,0.0f,     //v1
		0.0f,1.0f,0.0f,1.0f, //c1
		0.5f,-0.5f,0.0f,     //v2
		0.0f,0.0f,1.0f,1.0f, //c2
};

GLuint loadShader(GLenum type, const char* prog)
{
	GLuint shader = glCreateShader(type);
	if (shader == 0)
	{
		return 0;
	}
	glShaderSource(shader, 1, &prog, NULL);
	glCompileShader(shader);

	GLint compile;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &compile);
	if (!compile)
	{
		GLint length;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
		if (length > 0)
		{
			char* info = new char[length];
			glGetShaderInfoLog(shader, length, NULL, info);
			std::cerr << "compile error:" << info << std::endl;
			delete[] info;
			return 0;
		}
	}
	return shader;
	///if()
}

void InitVBO()
{
	glGenBuffers(2, vbo);


	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(GLfloat), vertices, GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLshort) * 3, indices, GL_STATIC_DRAW);
}

void InitVAO()
{
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 7, (void*)0);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 7, (void*)(0 + sizeof(GLfloat) * 3));

	glBindVertexArray(0);
}

bool InitShader()
{
	const char vShaderStr[] =
		"#version 300 es                            \n"
		"layout(location = 0) in vec4 a_position;   \n"
		"layout(location = 1) in vec4 a_color;      \n"
		"out vec4 v_color;                          \n"
		"void main()                                \n"
		"{                                          \n"
		"    v_color = a_color;                     \n"
		"    gl_Position = a_position;              \n"
		"}";


	const char fShaderStr[] =
		"#version 300 es            \n"
		"precision mediump float;   \n"
		"in vec4 v_color;           \n"
		"out vec4 o_fragColor;      \n"
		"void main()                \n"
		"{                          \n"
		"    o_fragColor = v_color; \n"
		"}";

	GLuint vshader = loadShader(GL_VERTEX_SHADER, vShaderStr);
	if (vshader == 0)
	{
		return false;
	}

	GLuint fshader = loadShader(GL_FRAGMENT_SHADER, fShaderStr);
	if (fshader == 0)
	{
		glDeleteShader(vshader);
		return false;
	}
	prog = glCreateProgram();
	if (prog == 0)
	{
		glDeleteShader(vshader);
		glDeleteShader(fshader);
	}

	glAttachShader(prog, vshader);
	glAttachShader(prog, fshader);

	glLinkProgram(prog);

	GLint linkstatus;
	glGetProgramiv(prog, GL_LINK_STATUS, &linkstatus);
	if (!linkstatus)
	{
		GLint length;
		glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &length);
		if (length > 0)
		{
			char* info = new char[length];
			glGetProgramInfoLog(prog, length, NULL, info);
			std::cerr << " prog link err:" << info << std::endl;
			delete[] info;
			glDeleteProgram(prog);
			return false;
		}
	}

	glDeleteShader(vshader);
	glDeleteShader(fshader);

	return true;
}
bool InitGL()
{
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glViewport(0, 0,600, 600);
	
	InitVBO();

	InitVAO();

	InitShader();
	return true;
}

void drawVBO()
{
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 7, (void*)0);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 7, (void*)(0 + sizeof(GLfloat) * 3));


	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);


	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}
void DrawVAO()
{
	glBindVertexArray(vao);
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
	glBindVertexArray(0);
}

void Draw()
{
	if (display == nullptr)
	{
		return;
	}
	glClear(GL_COLOR_BUFFER_BIT);
	glUseProgram(prog);
	
	///drawVBO();
	DrawVAO();

	eglSwapBuffers(display, surface);
}

LRESULT WINAPI eglWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT  lRet = 1;

	switch (uMsg)
	{
	case WM_CREATE:
		break;

	case WM_PAINT:
	{
		Draw();
		break;
	}
	break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	case WM_CHAR:
	{
		break;
	}
	break;

	default:
		lRet = DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
	}

	return lRet;
}

int main()
{

	WNDCLASSEX wnd = {};
	wnd.cbSize = sizeof(WNDCLASSEX);
	wnd.lpszClassName = "eglWindow";
	wnd.lpfnWndProc = eglWndProc;
	wnd.style = CS_OWNDC;
	
 	if (!RegisterClassEx(&wnd))
	{
		return 0;
	}

	DWORD wStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;

	HWND hwnd = CreateWindowEx(NULL, "eglWIndow", "eglWindow", wStyle, 50, 50, 600, 600, NULL, NULL, NULL, NULL);

	
	if (hwnd == NULL)
	{
		return 0;
	}

	ShowWindow(hwnd, SW_SHOW);
	

	display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	if(display == EGL_NO_DISPLAY)
	{ 
		return 0;
	}

	EGLint major, minor;
	if (!eglInitialize(display, &major, &minor))
	{
		return 0;
	}

	EGLint num_config;
	if (eglGetConfigs(display, NULL, 0, &num_config) == EGL_FALSE)
	{
		return 0;
	}

	EGLConfig* config = new EGLConfig[num_config];
	if (eglGetConfigs(display, config, num_config, &num_config) == EGL_FALSE)
	{
		return 0;
	}

	surface = eglCreateWindowSurface(display, config[0], hwnd, NULL);

	if (surface == EGL_NO_SURFACE)
	{
		return 0;
	}

	EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };

	EGLContext context = eglCreateContext(display, config[0], EGL_NO_CONTEXT, contextAttribs);
	if (context == EGL_NO_CONTEXT)
	{
		return 0;
	}

	if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
	{
		EGLint err = eglGetError();
		
		return 0;
	}

	InitGL();

	bool done = false;
	MSG msg = {};
	DWORD lastTime = GetTickCount();

	while (!done)
	{
		bool hasmsg = PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE);
		DWORD current = GetTickCount();
		float deltaTime = (float)(current - lastTime) / 1000.0f;
		lastTime = current;
		
		if (hasmsg)
		{
			if (msg.message == WM_QUIT)
			{
				done = true;
			}
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		else
		{
			SendMessage(hwnd, WM_PAINT, 0, 0);
		}
	}
	std::cout << "hello world" << std::endl;
	return 0;
}
